#include "core/main.h"

template <class type> void Grid<type>::Allocate(unsigned int Rows, unsigned int Cols)
{
    _rows = Rows;
    _cols = Cols;
    if(_data)
    {
        delete[] _data;
    }
    _data = new type[Rows * Cols];
}

template <class type> void Grid<type>::Allocate(unsigned int Rows, unsigned int Cols, const type &clearValue)
{
    _rows = Rows;
    _cols = Cols;
    if(_data)
    {
        delete[] _data;
    }
    _data = new type[Rows * Cols];
    Clear(clearValue);
}

template <class type> void Grid<type>::Clear(const type &T)
{
    const unsigned int TotalEntries = _rows * _cols;
    for(unsigned int Index = 0; Index < TotalEntries; Index++)
    {
        _data[Index] = T;
    }
}

template <class type> Vec2i Grid<type>::MaxIndex() const
{
    Vec2i maxIndex(0, 0);
    const type *maxValue = &_data[0];
    for(unsigned int rowIndex = 0; rowIndex < _rows; rowIndex++)
    {
        for(unsigned int colIndex = 0; colIndex < _cols; colIndex++)
        {
            const type *curValue = &_data[rowIndex * _cols + colIndex];
            if(*curValue > *maxValue)
            {
                maxIndex = Vec2i(rowIndex, colIndex);
                maxValue = curValue;
            }
        }
    }
    return maxIndex;
}

template <class type> const type& Grid<type>::MaxValue() const
{
    Vec2i index = MaxIndex();
    return _data[index.x * _cols + index.y];
}

template <class type> Vec2i Grid<type>::MinIndex() const
{
    Vec2i minIndex(0, 0);
    const type *minValue = &_data[0];
    for(unsigned int rowIndex = 0; rowIndex < _rows; rowIndex++)
    {
        for(unsigned int colIndex = 0; colIndex < _cols; colIndex++)
        {
            const type *curValue = &_data[rowIndex * _cols + colIndex];
            if(*curValue < *minValue)
            {
                minIndex = Vec2i(rowIndex, colIndex);
                minValue = curValue;
            }
        }
    }
    return minIndex;
}

template <class type> const type& Grid<type>::MinValue() const
{
    Vec2i index = MinIndex();
    return _data[index.x * _cols + index.y];
}

template <class type> Grid<type>::Grid()
{
    _rows = 0;
    _cols = 0;
    _data = NULL;
}

template <class type> Grid<type>::Grid(unsigned int Rows, unsigned int Cols)
{
    _rows = Rows;
    _cols = Cols;
    _data = new type[Rows * Cols];
}

template <class type> Grid<type>::Grid(unsigned int Rows, unsigned int Cols, const type &clearValue)
{
    _rows = Rows;
    _cols = Cols;
    _data = new type[Rows * Cols];
    Clear(clearValue);
}

template <class type> Grid<type>::Grid(const Grid<type> &G)
{
    _rows = G._rows;
    _cols = G._cols;

    const unsigned int TotalEntries = _rows * _cols;
    _data = new type[TotalEntries];
    for(unsigned int Index = 0; Index < TotalEntries; Index++)
    {
        _data[Index] = G._data[Index];
    }
}

template <class type> Grid<type>::~Grid()
{
    FreeMemory();
}

template <class type> void Grid<type>::FreeMemory()
{
    _rows = 0;
    _cols = 0;
    if(_data != NULL)
    {
        delete[] _data;
        _data = NULL;
    }
}

template <class type> void Grid<type>::operator = (const Grid<type> &G)
{
    if(_data)
    {
        delete[] _data;
    }
    _rows = G._rows;
    _cols = G._cols;

    const unsigned int TotalEntries = _rows * _cols;
    _data = new type[TotalEntries];
    for(unsigned int Index = 0; Index < TotalEntries; Index++)
    {
        _data[Index] = G._data[Index];
    }
}
